package com.yifushidai.api;

import com.github.pagehelper.PageInfo;
import com.yifushidai.entity.ApiUniqueMac;
import com.yifushidai.entity.DynamicTempkey;
import com.yifushidai.mapper.ApiUniqueMacMapper;
import com.yifushidai.mapper.KeypassBandEntityMapper;
import com.yifushidai.mapper.OptDeviceLogMapper;
import com.yifushidai.service.DynamicTempkeyService;
import com.yifushidai.task.MyRunnable;
import com.yifushidai.utils.ApiBaseAction;
import com.yifushidai.utils.ErrorCodeEnum;
import com.yifushidai.utils.Res;
import io.swagger.annotations.*;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

@RestController
@Api(tags = "动态密码")
@RequestMapping("/api/dynamicTempkey")
public class DynamicTempkeyTask extends ApiBaseAction {
    public static ConcurrentHashMap<String, ScheduledFuture<?>> scheduledFutureConcurrentHashMap = new ConcurrentHashMap<>();//线程安全  定时任务

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ApiUniqueMacMapper apiUniqueMacMapper;
    @Autowired
    private OptDeviceLogMapper optDeviceLogMapper;
    @Autowired
    private KeypassBandEntityMapper keyPassMapper;
    @Autowired
    private DynamicTempkeyService dynamicTempkeyService;
    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    @ApiOperation(value = "查询列表")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "token", value = "token", required = true),
    })
    @PostMapping("/queryList")
    public Res<DynamicTempkey> queryList(@ApiParam(value = "联网盒mac", required = true) @RequestParam String mac) {
        List<DynamicTempkey> dynamicTempkeyList = dynamicTempkeyService.queryListByMac(mac);
        PageInfo<DynamicTempkey> pageInfo = new PageInfo<DynamicTempkey>(dynamicTempkeyList);
        return Res.ok().datas(pageInfo.getList()).count(pageInfo.getTotal());
    }

    @ApiOperation(value = "启动", notes = "日期参数，格式为：yyyy-MM-dd HH:mm:ss" +
            "\n\n特别注意以下重要规则：" +
            "\n\n1. 该方法包含保存或更新（通过mac和pushIndex字段更新）；" +
            "\n\n2. expireDate参数需大于pushDate参数时间，且大于当前时间；" +
            "\n\n3. pushIndex参数唯一。")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "token", value = "token", required = true),
            @ApiImplicitParam(paramType = "query", name = "mac", value = "联网盒mac", required = true),
            @ApiImplicitParam(paramType = "query", name = "pushIndex", value = "推送索引", required = true),
            @ApiImplicitParam(paramType = "query", name = "pushDate", value = "推送时间", required = true, dataType = "date-time"),
            @ApiImplicitParam(paramType = "query", name = "expireDate", value = "失效时间", required = true, dataType = "date-time"),
    })
    @PostMapping("/startCron")
    public Res startCron(@ModelAttribute DynamicTempkey record) throws ParseException {
//        if (record.getPushDate().getTime() <= new Date().getTime()) {
//            return Res.error("推送时间设置有误");
//        }
        if (record.getExpireDate().getTime() <= record.getPushDate().getTime()
                || record.getExpireDate().getTime() <= new Date().getTime()) {
            return Res.error("失效时间设置有误");
        }
        for (Map.Entry<String, ScheduledFuture<?>> e : scheduledFutureConcurrentHashMap.entrySet()) {
            if (e.getKey().startsWith(record.getMac() + record.getPushIndex())) {
                e.getValue().cancel(true);
                scheduledFutureConcurrentHashMap.remove(e.getKey());
            }
        }
        String tempKey = RandomStringUtils.randomNumeric(4);//4位 随机数
        record.setTempKey(tempKey);

        ApiUniqueMac one = apiUniqueMacMapper.selectOne(ApiUniqueMac.builder().mac(record.getMac()).build());
        if (null == one) return Res.error(ErrorCodeEnum.MAC_NULL);

        scheduledFutureConcurrentHashMap.put(record.getMac() + record.getPushIndex() + "A",
                threadPoolTaskScheduler.schedule(new MyRunnable(optDeviceLogMapper, keyPassMapper, one, tempKey, record.getExpireDate()), record.getPushDate()));
        // 必须发xxxx，保证用户有效期间未开门，也能超时失效
        scheduledFutureConcurrentHashMap.put(record.getMac() + record.getPushIndex() + "B",
                threadPoolTaskScheduler.schedule(new MyRunnable(optDeviceLogMapper, keyPassMapper, one, "xxxx", record.getExpireDate()), record.getExpireDate()));

        if (dynamicTempkeyService.saveOrUpdate(record) > 0) {
            String key = "TK_" + record.getMac() + "_" + record.getPushIndex();
            ValueOperations<String, DynamicTempkey> operations = redisTemplate.opsForValue();
            operations.set(key, record);
            redisTemplate.expireAt(key, record.getExpireDate());

            return Res.ok().datas(tempKey);
        } else {
            return Res.error();
        }
    }

    @ApiOperation(value = "停止")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "token", value = "token", required = true),
            @ApiImplicitParam(paramType = "query", name = "mac", value = "联网盒mac", required = true),
            @ApiImplicitParam(paramType = "query", name = "pushIndex", value = "推送索引", required = true),
    })
    @PostMapping("/stopCron")
    public Res stopCron(@ModelAttribute DynamicTempkey record) {
        for (Map.Entry<String, ScheduledFuture<?>> e : scheduledFutureConcurrentHashMap.entrySet()) {
            if (e.getKey().startsWith(record.getMac() + record.getPushIndex())) {
                e.getValue().cancel(true);
                scheduledFutureConcurrentHashMap.remove(e.getKey());
            }
        }

        if (dynamicTempkeyService.deleteByMacAndPushIndex(record) > 0) {
            return Res.ok();
        } else {
            return Res.error();
        }
    }

    @ApiOperation(value = "停止当前设备")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "token", value = "token", required = true),
            @ApiImplicitParam(paramType = "query", name = "mac", value = "联网盒mac", required = true),
    })
    @PostMapping("/stopCronByMac")
    public Res stopCronByMac(@ModelAttribute DynamicTempkey record) {
        for (Map.Entry<String, ScheduledFuture<?>> e : scheduledFutureConcurrentHashMap.entrySet()) {
            if (e.getKey().startsWith(record.getMac())) {
                e.getValue().cancel(true);
                scheduledFutureConcurrentHashMap.remove(e.getKey());
            }
        }

        dynamicTempkeyService.deleteByMac(record);
        return Res.ok();
    }
}